{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b8aed906",
   "metadata": {},
   "source": [
    "## 启动 MongoDB"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "5fdbf81c",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-10-31T02:30:00.385568Z",
     "start_time": "2023-10-31T02:27:45.121736Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/Users/macbook/opt/mongodb/bin\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.517+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":4915701, \"ctx\":\"thread1\",\"msg\":\"Initialized wire specification\",\"attr\":{\"spec\":{\"incomingExternalClient\":{\"minWireVersion\":0,\"maxWireVersion\":21},\"incomingInternalClient\":{\"minWireVersion\":0,\"maxWireVersion\":21},\"outgoing\":{\"minWireVersion\":6,\"maxWireVersion\":21},\"isInternalClient\":true}}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.521+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":23285,   \"ctx\":\"thread1\",\"msg\":\"Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.523+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":4648602, \"ctx\":\"thread1\",\"msg\":\"Implicit TCP FastOpen in use.\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.531+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":5123008, \"ctx\":\"thread1\",\"msg\":\"Successfully registered PrimaryOnlyService\",\"attr\":{\"service\":\"TenantMigrationDonorService\",\"namespace\":\"config.tenantMigrationDonors\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.532+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":5123008, \"ctx\":\"thread1\",\"msg\":\"Successfully registered PrimaryOnlyService\",\"attr\":{\"service\":\"TenantMigrationRecipientService\",\"namespace\":\"config.tenantMigrationRecipients\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.532+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":5945603, \"ctx\":\"thread1\",\"msg\":\"Multi threading initialized\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.532+08:00\"},\"s\":\"I\",  \"c\":\"TENANT_M\", \"id\":7091600, \"ctx\":\"thread1\",\"msg\":\"Starting TenantMigrationAccessBlockerRegistry\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.532+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4615611, \"ctx\":\"initandlisten\",\"msg\":\"MongoDB starting\",\"attr\":{\"pid\":87139,\"port\":27017,\"dbPath\":\"../data\",\"architecture\":\"64-bit\",\"host\":\"macbookdeMacBook-Air.local\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.532+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":23403,   \"ctx\":\"initandlisten\",\"msg\":\"Build Info\",\"attr\":{\"buildInfo\":{\"version\":\"7.0.2\",\"gitVersion\":\"02b3c655e1302209ef046da6ba3ef6749dd0b62a\",\"modules\":[],\"allocator\":\"system\",\"environment\":{\"distarch\":\"aarch64\",\"target_arch\":\"aarch64\"}}}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.532+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":51765,   \"ctx\":\"initandlisten\",\"msg\":\"Operating System\",\"attr\":{\"os\":{\"name\":\"Mac OS X\",\"version\":\"22.3.0\"}}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.532+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":21951,   \"ctx\":\"initandlisten\",\"msg\":\"Options set by command line\",\"attr\":{\"options\":{\"storage\":{\"dbPath\":\"../data\"}}}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.534+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":5693100, \"ctx\":\"initandlisten\",\"msg\":\"Asio socket.set_option failed with std::system_error\",\"attr\":{\"note\":\"acceptor TCP fast open\",\"option\":{\"level\":6,\"name\":261,\"data\":\"00 04 00 00\"},\"error\":{\"what\":\"set_option: Invalid argument\",\"message\":\"Invalid argument\",\"category\":\"asio.system\",\"value\":22}}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.535+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22270,   \"ctx\":\"initandlisten\",\"msg\":\"Storage engine to use detected by data files\",\"attr\":{\"dbpath\":\"../data\",\"storageEngine\":\"wiredTiger\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:45.536+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22315,   \"ctx\":\"initandlisten\",\"msg\":\"Opening WiredTiger\",\"attr\":{\"config\":\"create,cache_size=3584M,session_max=33000,eviction=(threads_min=4,threads_max=4),config_base=false,statistics=(fast),log=(enabled=true,remove=true,path=journal,compressor=snappy),builtin_extension_config=(zstd=(compression_level=6)),file_manager=(close_idle_time=600,close_scan_interval=10,close_handle_minimum=2000),statistics_log=(wait=0),json_output=(error,message),verbose=[recovery_progress:1,checkpoint_progress:1,compact_progress:1,backup:0,checkpoint:0,compact:0,evict:0,history_store:0,recovery:0,rts:0,salvage:0,tiered:0,timestamp:0,transaction:0,verify:0,log:0],\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.331+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":4795906, \"ctx\":\"initandlisten\",\"msg\":\"WiredTiger opened\",\"attr\":{\"durationMillis\":795}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.331+08:00\"},\"s\":\"I\",  \"c\":\"RECOVERY\", \"id\":23987,   \"ctx\":\"initandlisten\",\"msg\":\"WiredTiger recoveryTimestamp\",\"attr\":{\"recoveryTimestamp\":{\"$timestamp\":{\"t\":0,\"i\":0}}}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.342+08:00\"},\"s\":\"W\",  \"c\":\"CONTROL\",  \"id\":22120,   \"ctx\":\"initandlisten\",\"msg\":\"Access control is not enabled for the database. Read and write access to data and configuration is unrestricted\",\"tags\":[\"startupWarnings\"]}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.342+08:00\"},\"s\":\"W\",  \"c\":\"CONTROL\",  \"id\":22140,   \"ctx\":\"initandlisten\",\"msg\":\"This server is bound to localhost. Remote systems will be unable to connect to this server. Start the server with --bind_ip <address> to specify which IP addresses it should serve responses from, or with --bind_ip_all to bind to all interfaces. If this behavior is desired, start the server with --bind_ip 127.0.0.1 to disable this warning\",\"tags\":[\"startupWarnings\"]}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.342+08:00\"},\"s\":\"W\",  \"c\":\"CONTROL\",  \"id\":22184,   \"ctx\":\"initandlisten\",\"msg\":\"Soft rlimits for open file descriptors too low\",\"attr\":{\"currentValue\":4096,\"recommendedMinimum\":64000},\"tags\":[\"startupWarnings\"]}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.348+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":4915702, \"ctx\":\"initandlisten\",\"msg\":\"Updated wire specification\",\"attr\":{\"oldSpec\":{\"incomingExternalClient\":{\"minWireVersion\":0,\"maxWireVersion\":21},\"incomingInternalClient\":{\"minWireVersion\":0,\"maxWireVersion\":21},\"outgoing\":{\"minWireVersion\":6,\"maxWireVersion\":21},\"isInternalClient\":true},\"newSpec\":{\"incomingExternalClient\":{\"minWireVersion\":0,\"maxWireVersion\":21},\"incomingInternalClient\":{\"minWireVersion\":21,\"maxWireVersion\":21},\"outgoing\":{\"minWireVersion\":21,\"maxWireVersion\":21},\"isInternalClient\":true}}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.348+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":5853300, \"ctx\":\"initandlisten\",\"msg\":\"current featureCompatibilityVersion value\",\"attr\":{\"featureCompatibilityVersion\":\"7.0\",\"context\":\"startup\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.348+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":5071100, \"ctx\":\"initandlisten\",\"msg\":\"Clearing temp directory\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.351+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":6608200, \"ctx\":\"initandlisten\",\"msg\":\"Initializing cluster server parameters from disk\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.351+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":20536,   \"ctx\":\"initandlisten\",\"msg\":\"Flow Control is enabled on this deployment\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.351+08:00\"},\"s\":\"I\",  \"c\":\"FTDC\",     \"id\":20625,   \"ctx\":\"initandlisten\",\"msg\":\"Initializing full-time diagnostic data capture\",\"attr\":{\"dataDirectory\":\"../data/diagnostic.data\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.359+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":6015317, \"ctx\":\"initandlisten\",\"msg\":\"Setting new configuration state\",\"attr\":{\"newState\":\"ConfigReplicationDisabled\",\"oldState\":\"ConfigPreStart\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.359+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22262,   \"ctx\":\"initandlisten\",\"msg\":\"Timestamp monitor starting\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.359+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":23015,   \"ctx\":\"listener\",\"msg\":\"Listening on\",\"attr\":{\"address\":\"/tmp/mongodb-27017.sock\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.359+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":23015,   \"ctx\":\"listener\",\"msg\":\"Listening on\",\"attr\":{\"address\":\"127.0.0.1\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:46.359+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":23016,   \"ctx\":\"listener\",\"msg\":\"Waiting for connections\",\"attr\":{\"port\":27017,\"ssl\":\"off\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:50.874+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":22943,   \"ctx\":\"listener\",\"msg\":\"Connection accepted\",\"attr\":{\"remote\":\"127.0.0.1:51779\",\"uuid\":{\"uuid\":{\"$uuid\":\"90ca63a5-45ef-48d2-8faa-32df69a5a179\"}},\"connectionId\":1,\"connectionCount\":1}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:50.875+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":51800,   \"ctx\":\"conn1\",\"msg\":\"client metadata\",\"attr\":{\"remote\":\"127.0.0.1:51779\",\"client\":\"conn1\",\"doc\":{\"application\":{\"name\":\"MongoDB Compass\"},\"driver\":{\"name\":\"nodejs\",\"version\":\"6.0.0\"},\"platform\":\"Node.js v18.15.0, LE\",\"os\":{\"name\":\"darwin\",\"architecture\":\"arm64\",\"version\":\"22.3.0\",\"type\":\"Darwin\"}}}}\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"t\":{\"$date\":\"2023-10-31T10:27:50.952+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":22943,   \"ctx\":\"listener\",\"msg\":\"Connection accepted\",\"attr\":{\"remote\":\"127.0.0.1:51781\",\"uuid\":{\"uuid\":{\"$uuid\":\"78f4d7e7-854e-4764-9684-88007ae4260d\"}},\"connectionId\":2,\"connectionCount\":2}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:27:50.962+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":51800,   \"ctx\":\"conn2\",\"msg\":\"client metadata\",\"attr\":{\"remote\":\"127.0.0.1:51781\",\"client\":\"conn2\",\"doc\":{\"application\":{\"name\":\"MongoDB Compass\"},\"driver\":{\"name\":\"nodejs\",\"version\":\"6.1.0\"},\"platform\":\"Node.js v18.15.0, LE\",\"os\":{\"name\":\"darwin\",\"architecture\":\"arm64\",\"version\":\"22.3.0\",\"type\":\"Darwin\"}}}}\n",
      "^C\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.218+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":23377,   \"ctx\":\"SignalHandler\",\"msg\":\"Received signal\",\"attr\":{\"signal\":2,\"error\":\"Interrupt: 2\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.218+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":23381,   \"ctx\":\"SignalHandler\",\"msg\":\"will terminate after current cmd ends\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.218+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":4784900, \"ctx\":\"SignalHandler\",\"msg\":\"Stepping down the ReplicationCoordinator for shutdown\",\"attr\":{\"waitTimeMillis\":15000}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.220+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":4794602, \"ctx\":\"SignalHandler\",\"msg\":\"Attempting to enter quiesce mode\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.220+08:00\"},\"s\":\"I\",  \"c\":\"-\",        \"id\":6371601, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the FLE Crud thread pool\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.220+08:00\"},\"s\":\"I\",  \"c\":\"COMMAND\",  \"id\":4784901, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the MirrorMaestro\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"SHARDING\", \"id\":4784902, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the WaitForMajorityService\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4784903, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the LogicalSessionCache\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":20562,   \"ctx\":\"SignalHandler\",\"msg\":\"Shutdown: going to close listening sockets\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":23017,   \"ctx\":\"listener\",\"msg\":\"removing socket file\",\"attr\":{\"path\":\"/tmp/mongodb-27017.sock\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":4784905, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the global connection pool\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4784906, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the FlowControlTicketholder\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"-\",        \"id\":20520,   \"ctx\":\"SignalHandler\",\"msg\":\"Stopping further Flow Control ticket acquisitions.\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.221+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4784908, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the PeriodicThreadToAbortExpiredTransactions\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.222+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":4784909, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the ReplicationCoordinator\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.222+08:00\"},\"s\":\"I\",  \"c\":\"SHARDING\", \"id\":4784910, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the ShardingInitializationMongoD\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.222+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":4784911, \"ctx\":\"SignalHandler\",\"msg\":\"Enqueuing the ReplicationStateTransitionLock for shutdown\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.222+08:00\"},\"s\":\"I\",  \"c\":\"-\",        \"id\":4784912, \"ctx\":\"SignalHandler\",\"msg\":\"Killing all operations for shutdown\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.222+08:00\"},\"s\":\"I\",  \"c\":\"-\",        \"id\":4695300, \"ctx\":\"SignalHandler\",\"msg\":\"Interrupted all currently running operations\",\"attr\":{\"opsKilled\":5}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.222+08:00\"},\"s\":\"I\",  \"c\":\"TENANT_M\", \"id\":5093807, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down all TenantMigrationAccessBlockers on global shutdown\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.222+08:00\"},\"s\":\"I\",  \"c\":\"ASIO\",     \"id\":22582,   \"ctx\":\"TenantMigrationBlockerNet\",\"msg\":\"Killing all outstanding egress activity.\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.223+08:00\"},\"s\":\"I\",  \"c\":\"ASIO\",     \"id\":6529201, \"ctx\":\"SignalHandler\",\"msg\":\"Network interface redundant shutdown\",\"attr\":{\"state\":\"Stopped\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.223+08:00\"},\"s\":\"I\",  \"c\":\"ASIO\",     \"id\":22582,   \"ctx\":\"SignalHandler\",\"msg\":\"Killing all outstanding egress activity.\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.223+08:00\"},\"s\":\"I\",  \"c\":\"COMMAND\",  \"id\":4784913, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down all open transactions\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.223+08:00\"},\"s\":\"I\",  \"c\":\"REPL\",     \"id\":4784914, \"ctx\":\"SignalHandler\",\"msg\":\"Acquiring the ReplicationStateTransitionLock for shutdown\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.223+08:00\"},\"s\":\"I\",  \"c\":\"INDEX\",    \"id\":4784915, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the IndexBuildsCoordinator\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.223+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":4784918, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the ReplicaSetMonitor\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.223+08:00\"},\"s\":\"I\",  \"c\":\"SHARDING\", \"id\":4784921, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the MigrationUtilExecutor\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"ASIO\",     \"id\":22582,   \"ctx\":\"MigrationUtil-TaskExecutor\",\"msg\":\"Killing all outstanding egress activity.\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"COMMAND\",  \"id\":4784923, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the ServiceEntryPoint\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4784927, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the HealthLog\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4784928, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the TTL monitor\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"INDEX\",    \"id\":3684100, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down TTL collection monitor thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"INDEX\",    \"id\":3684101, \"ctx\":\"SignalHandler\",\"msg\":\"Finished shutting down TTL collection monitor thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":6278511, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the Change Stream Expired Pre-images Remover\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4784929, \"ctx\":\"SignalHandler\",\"msg\":\"Acquiring the global lock for shutdown\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":4784930, \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down the storage engine\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22320,   \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down journal flusher thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22321,   \"ctx\":\"SignalHandler\",\"msg\":\"Finished shutting down journal flusher thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22322,   \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down checkpoint thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22323,   \"ctx\":\"SignalHandler\",\"msg\":\"Finished shutting down checkpoint thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22261,   \"ctx\":\"SignalHandler\",\"msg\":\"Timestamp monitor shutting down\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":20282,   \"ctx\":\"SignalHandler\",\"msg\":\"Deregistering all the collections\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22317,   \"ctx\":\"SignalHandler\",\"msg\":\"WiredTigerKVEngine shutting down\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22318,   \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down session sweeper thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22319,   \"ctx\":\"SignalHandler\",\"msg\":\"Finished shutting down session sweeper thread\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.224+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":4795902, \"ctx\":\"SignalHandler\",\"msg\":\"Closing WiredTiger\",\"attr\":{\"closeConfig\":\"leak_memory=true,use_timestamp=false,\"}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.226+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":22944,   \"ctx\":\"conn1\",\"msg\":\"Connection ended\",\"attr\":{\"remote\":\"127.0.0.1:51779\",\"uuid\":{\"uuid\":{\"$uuid\":\"90ca63a5-45ef-48d2-8faa-32df69a5a179\"}},\"connectionId\":1,\"connectionCount\":1}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.227+08:00\"},\"s\":\"I\",  \"c\":\"NETWORK\",  \"id\":22944,   \"ctx\":\"conn2\",\"msg\":\"Connection ended\",\"attr\":{\"remote\":\"127.0.0.1:51781\",\"uuid\":{\"uuid\":{\"$uuid\":\"78f4d7e7-854e-4764-9684-88007ae4260d\"}},\"connectionId\":2,\"connectionCount\":0}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.267+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":4795901, \"ctx\":\"SignalHandler\",\"msg\":\"WiredTiger closed\",\"attr\":{\"durationMillis\":43}}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.267+08:00\"},\"s\":\"I\",  \"c\":\"STORAGE\",  \"id\":22279,   \"ctx\":\"SignalHandler\",\"msg\":\"shutdown: removing fs lock...\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.267+08:00\"},\"s\":\"I\",  \"c\":\"-\",        \"id\":4784931, \"ctx\":\"SignalHandler\",\"msg\":\"Dropping the scope cache for shutdown\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.267+08:00\"},\"s\":\"I\",  \"c\":\"FTDC\",     \"id\":20626,   \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down full-time diagnostic data capture\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.272+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":20565,   \"ctx\":\"SignalHandler\",\"msg\":\"Now exiting\"}\n",
      "{\"t\":{\"$date\":\"2023-10-31T10:30:00.272+08:00\"},\"s\":\"I\",  \"c\":\"CONTROL\",  \"id\":23138,   \"ctx\":\"SignalHandler\",\"msg\":\"Shutting down\",\"attr\":{\"exitCode\":0}}\n"
     ]
    }
   ],
   "source": [
    "%cd /Users/macbook/opt/mongodb/bin\n",
    "!./mongod --dbpath=../data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "937ab106",
   "metadata": {},
   "source": [
    "## MongoDB的简单使用"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23b90ad6",
   "metadata": {},
   "source": [
    "- **db:**  当前正在使用的数据库\n",
    "- **show dbs:**  显示所有数据库\n",
    "- **show databases:**  显示所有数据库\n",
    "- **use xxxx:**  调整操作的数据库\n",
    "- **db.dropDatabase():**  删除正在使用的数据库\n",
    "- **show collections:**  显示当前数据库中所有的集合(表)\n",
    "- **db.collection_name.insert({})**\n",
    "- **db.createCollection(name, {options})**  创建集合     capped:是否卷动, size:大小\n",
    "- **db.collection_name.drop()**   删除集合\n",
    "- **db.collection_name.insert()**   向集合中添加数据( 如果该集合不存在, 自动创建)\n",
    "- **Db.collection_name.isCapped()**  判断是否有容量上限(判断该集合是否是固定容量的集合)\n",
    "\n",
    "- **换行**: shift + enter"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78227d13",
   "metadata": {},
   "source": [
    "## MongoDB 中常见的数据类型:\n",
    "\n",
    "\n",
    "- **Object ID:**  主键ID\n",
    "- **String:**  字符串\n",
    "- **Boolean:**  布尔值\n",
    "- **Integer:**  数字\n",
    "- **Doube:**  小数\n",
    "- **Arrays:**  数组\n",
    "- **Object:**  文档(关联其他对象)  {sname: 李嘉诚, sage: 18, class:{cccc}}\n",
    "- **Null:**  空值\n",
    "- **Timestamp:**  时间戳\n",
    "- **Date:**  时间日期\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe03b19b",
   "metadata": {},
   "source": [
    "## MongoDB的增删改查"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "23a5d42f",
   "metadata": {},
   "source": [
    "### MongoDB 添加数据\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1fa79e4",
   "metadata": {},
   "source": [
    "```mongo\n",
    "db.collection_name.insertOne({字段:值,字段:值})\n",
    "\n",
    "db.collection_name.insertMany([{字段:值,字段:值},\n",
    "                               {字段:值,字段:值},\n",
    "                               {字段:值,字段:值}])\n",
    "```\n",
    "\n",
    "示例:\n",
    "\n",
    "```mongo\n",
    "db.stu.insertOne({name:\"小猪\", age:18, hobby:[\"吃\", \"喝\", \"拉撒睡\"]})\n",
    "\n",
    "db.stu.insertMany([{name:\"小猪\", age:18, hobby:[\"吃\", \"喝\", \"拉撒睡\"]},\n",
    "                   {name:\"小羊\", age:18, hobby:[\"吃\", \"喝\", \"拉撒睡\"]},\n",
    "                   {name:\"小红\", age:18, hobby:[\"吃\", \"喝\", \"拉撒睡\"]}])\n",
    "```\n",
    "\n",
    "注意, 如果集合不存在，则会自动创建集合"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69e64bd6",
   "metadata": {},
   "source": [
    "### mongodb修改数据\n",
    "\n",
    "**update更新:**\n",
    "\n",
    "```mongo\n",
    "db.collection_name.update({查询条件}, {待修改内容}, {multi: 是否多条数据修改, upsert:true})\n",
    "```\n",
    "\n",
    "示例:\n",
    "\n",
    "```mongo\n",
    "db.stu.update({name:\"小猪\"}, {$set:{title:\"alex\", hobby:[\"抽烟\", \"喝酒\", \"烫头\"]}}, {multi:true})\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86754ecd",
   "metadata": {},
   "source": [
    "### MongoDB删除数据\n",
    "\n",
    "**remove()**\n",
    "\n",
    "```\n",
    "db.collection_name.remove({条件}, {justOne:true|false})\n",
    "```\n",
    "\n",
    "示例:\n",
    "\n",
    "```\n",
    "db.stu.remove({name:\"小羊\"}, {justOne:true})\n",
    "```\n",
    "\n",
    "**deleteOne()**\n",
    "\n",
    "```\n",
    "db.collection_name.deleteOne({条件})\n",
    "```\n",
    "\n",
    "示例:\n",
    "\n",
    "```\n",
    "db.stu.deleteOne({name:\"小猪\"})\n",
    "```\n",
    "\n",
    "**deleteMandy()**\n",
    "\n",
    "```\n",
    "db.collection_name.deleteMany({条件})\n",
    "```\n",
    "\n",
    "示例:\n",
    "\n",
    "```\n",
    "db.stu.deleteMany({name:\"小猪\"})\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9af7350c",
   "metadata": {},
   "source": [
    "### MongoDB 查询数据\n",
    "\n",
    "#### 准备数据\n",
    "\n",
    "```\n",
    "db.stu.insert([\n",
    "    {name: \"朱元璋\", age:800, address:'安徽省凤阳', score: 160},\n",
    "    {name: \"朱棣\", age:750, address:'江苏省南京市', score: 120},\n",
    "    {name: \"朱高炽\", age:700, address:'北京紫禁城', score: 90},\n",
    "    {name: \"李嘉诚\", age:38, address:'香港xxx街道', score: 70},\n",
    "    {name: \"麻花藤\", age:28, address:'广东省xxx市', score: 80},\n",
    "    {name: \"大老王\", age:33, address:'火星第一卫星', score: -60},\n",
    "    {name: \"咩咩\", age:33, address:'开普勒225旁边的黑洞', score: -160}\n",
    "])\n",
    "```\n",
    "\n",
    "#### 普通查询\n",
    "\n",
    "```\n",
    "db.stu.find({条件})  查询所有\n",
    "db.stu.findOne({})  查询一个\n",
    "db.stu.find().pretty()  将查询出来的结果进行格式化(好看一些)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "854be2ad",
   "metadata": {},
   "source": [
    "#### 比较运算\n",
    "\n",
    "```\n",
    "等于： $eq，默认是等于判断\n",
    "小于： $lt （less than）\n",
    "小于等于： $lte （less than equal）\n",
    "大于： $gt （greater than）\n",
    "大于等于： $gte\n",
    "不等于： $ne\n",
    "```\n",
    "\n",
    "```\n",
    "db.stu.find({age:28})  查询年龄是28岁的学生信息\n",
    "db.stu.find({age: {$eq: 28}})  查询年龄是28岁的学生信息\n",
    "db.stu.find({age: {$gt: 30}})   查询年龄大于30岁的学生\n",
    "db.stu.find({age: {$lt: 30}})   查询年龄小于30岁的学生\n",
    "db.stu.find({age: {$gte: 38}})  查询年龄大于等于30岁的学生\n",
    "db.stu.find({age: {$lte: 38}})  查询年龄小于等于30岁的学生\n",
    "db.stu.find({age: {$ne: 38}})   查询年龄不等于38的学生\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7e8c1dd",
   "metadata": {},
   "source": [
    "#### 逻辑运算符\n",
    "\n",
    "**1. and**\n",
    "\n",
    "$and: [条件1, 条件2, 条件3....]\n",
    "\n",
    "\n",
    "```\n",
    "db.stu.find({$and:[{age: {$eq:33}}, {name:'大老王'}]})  查询年龄等于33, 并且, 名字是\"大老王\" 的学生信息\n",
    "```\n",
    "\n",
    "**2. or**\n",
    "\n",
    "$or: [条件1, 条件2, 条件3....]\n",
    "\n",
    "```\n",
    "db.stu.find({$or:[{name: '李嘉诚'}, {age: {$gt: 100}}]})  查询名字叫\"李嘉诚\"的, 或者, 年龄超过100岁的人\n",
    "```\n",
    "\n",
    "**3. nor**\n",
    "  \n",
    "$nor: [条件1, 条件2, 条件3...]\n",
    "  \n",
    "\n",
    "```\n",
    "db.stu.find({$nor:[{age: {$lt: 38}}, {name: \"朱元璋\"}]})  查询年龄不小于38岁的人, 名字还不能是朱元璋. \n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32693e53",
   "metadata": {},
   "source": [
    "#### 范围运算符\n",
    "\n",
    "使用 \\\\$in， \\\\$nin 判断数据 是否在某个数组内\n",
    "\n",
    "```\n",
    "db.stu.find({age: {$in:[28, 38]}})   年龄是 28 或者 38 的人\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "18cb5ea2",
   "metadata": {},
   "source": [
    "#### 正则表达式\n",
    "\n",
    "使用 $regex 进行正则表达式匹配\n",
    "\n",
    "```\n",
    "db.stu.find({address: {$regex:'^北京'}})  查询地址是北京的人的信息\n",
    "db.stu.find({address: /^北京/})  效果一样\n",
    "```\n",
    "\n",
    "#### 自定义查询(了解)\n",
    "\n",
    "mongo shell 是一个js的执行环境\n",
    "使用 $where 写一个函数， 返回满足条件的数据\n",
    "\n",
    "```\n",
    "db.stu.find({$where:function(){return this.age > 38;}})\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52256a43",
   "metadata": {},
   "source": [
    "\n",
    "#### skip 和 limit\n",
    "\n",
    "```\n",
    "db.stu.find().skip(3).limit(3)    \n",
    "```\n",
    "\n",
    "跳过3个，提取3个，类似limit 3, 3 可以用来做分页\n",
    "\n",
    "#### 投影\n",
    "\n",
    "投影可以控制最终查询的结果(字段筛选)\n",
    "\n",
    "```\n",
    "db.stu.find({}, {字段:1, 字段:1})\n",
    "```\n",
    "\n",
    "需要看的字段给1就可以了.\n",
    "\n",
    "注意, 除了\\_id外, 0, 1不能共存\n",
    "```\n",
    "db.stu.find({}, {\"name\":1, \"age\":1})\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2db48e97",
   "metadata": {},
   "source": [
    "#### 排序\n",
    "\n",
    "sort({字段:1, 字段:-1})\n",
    "\n",
    "1表示升序，-1表示降序\n",
    "\n",
    "```\n",
    "db.stu.find().sort({age:1, score: -1})  对查询结果排序, 先按照 age升序 排列, 相同项再按照 score降序 排列\n",
    "```\n",
    "\n",
    "#### 统计数量\n",
    "\n",
    "count(条件) 查询数量\n",
    "\n",
    "```\n",
    "db.stu.countDocuments({age:33})\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3d3bda8",
   "metadata": {},
   "source": [
    "## MongoDB的管道\n",
    "\n",
    "MongoDB管道 可以将多个操作依次执行, 并将上一次执行的结果传递给下一个管道表达式.\n",
    "\n",
    "**语法:**\n",
    "\n",
    "```\n",
    "db.collection_name.aggregate({管道:{表达式}}, {管道:{表达式}}, {管道:{表达式}}....)\n",
    "```\n",
    "\n",
    "**管道:** \n",
    "\n",
    "- \\$group , 对数据进行分组\n",
    "- \\$match, 对数据进行匹配\n",
    "- \\$project, 对数据进行修改结构, 重命名等\n",
    "- \\$sort, 将数据记性排序\n",
    "- \\$limit, 提取固定数量的数据\n",
    "- \\$skip, 跳过指定数量的数据\n",
    "\n",
    "**表达式:**\n",
    "- \\$sum, 求和\n",
    "- \\$avg, 计算平均值\n",
    "- \\$min, 最小值\n",
    "- \\$max, 最大值\n",
    "- \\$push, 在结果中插⼊值到⼀个数组中\n",
    "\n",
    "**案例:**\n",
    "\n",
    "```\n",
    "# 根据性别进行分组\n",
    "db.stu.aggregate({$group: {_id:'$gender'}})\n",
    "\n",
    "# 统计男生和女声的数量\n",
    "db.stu.aggregate({$group: {_id:'$gender', cou:{$sum: 1}}})  \n",
    "\n",
    "# 统计男生女生数量, 平均成绩以及最高分\n",
    "db.stu.aggregate({$group: {_id:'$gender', cou:{$sum:1}, \n",
    "                   avg_score: {$avg:'$score'}, \n",
    "                   max_score: {$max: '$score'}}})\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8ca7d74",
   "metadata": {},
   "source": [
    "**\\$push的使用：**\n",
    "\n",
    "想拿到分组后的人员名单, 此时就可以用\\$push将名称字段整理到一个列表中\n",
    "\n",
    "```\n",
    "db.stu.aggregate({$group: {_id:'$gender', cou:{$sum:1}, \n",
    "                   avg_score: {$avg:'$score'}, \n",
    "                   max_score: {$max: '$score'}, \n",
    "                   name_list: {$push: '$name'}}})\n",
    "```\n",
    "\n",
    "效果:\n",
    "```\n",
    "{\n",
    "    \"_id\" : false, \n",
    "    \"cou\" : 3, \n",
    "    \"avg_score\" : 123.33333333333333, \n",
    "    \"max_score\" : 160, \n",
    "    \"name_list\" : [ \"朱元璋\", \"朱棣\", \"朱高炽\" ] \n",
    "}\n",
    "\n",
    "{ \n",
    "    \"_id\" : true, \n",
    "    \"cou\" : 4, \n",
    "    \"avg_score\" : -17.5, \n",
    "    \"max_score\" : 80, \n",
    "    \"name_list\" : [ \"李嘉诚\", \"麻花藤\", \"大老王\", \"咩咩\" ] \n",
    "}\n",
    "```\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "64023610",
   "metadata": {},
   "source": [
    "**\\$match的使用：**\n",
    "\n",
    "可以对数据进行检索, 然后可以进入其它管道\n",
    "\n",
    "```\n",
    "db.stu.aggregate({$match:{age:{$gt:33}}}, {$group:{_id:\"$gender\", name_list:{$push:\"$name\"}}})\n",
    "```\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f9f5fc3",
   "metadata": {},
   "source": [
    "**\\$project的使用：**\n",
    "\n",
    "可以对管道中的数据进行投影\n",
    "\n",
    "```\n",
    "db.stu.aggregate({$match:{age:{$gt:33}}}, \n",
    "                {$group:{_id:\"$gender\", count:{$sum:1}, name_list:{$push:\"$name\"}}}, \n",
    "                {$project:{_id:0, name_list:1}})\n",
    "```\n",
    "\n",
    "**\\$sort的使用：**\n",
    "\n",
    "可以对管道中的数据进行排序\n",
    "\n",
    "```\n",
    "db.stu.aggregate({$match:{age:{$gt:33}}}, \n",
    "                {$group:{_id:\"$gender\", count:{$sum:1}, name_list:{$push:\"$name\"}}}, \n",
    "                {$sort:{count: 1}})\n",
    "```\n",
    "\n",
    "**\\\\$limit 和 \\\\$skip 的使用：**\n",
    "\n",
    "可以对管道中的数据进行分页查询\n",
    "\n",
    "```\n",
    "db.stu.aggregate({$match:{age:{$gt:33}}}, \n",
    "                {$group:{_id:\"$gender\", count:{$sum:1}, name_list:{$push:\"$name\"}}}, \n",
    "                {$sort:{count: 1}},\n",
    "                {$skip:1}, \n",
    "                {$limit:1})\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30155210",
   "metadata": {},
   "source": [
    "## MongoDB的索引操作\n",
    "\n",
    "索引可以非常明显的提高我们查询的效率. 但是要注意, 创建索引后, 对查询效率是有显著提高的. 但是对增加数据而言效率是会变低的.\n",
    "\n",
    "**添加索引:**\n",
    "\n",
    "```mongo\n",
    "db.collection_name.ensureIndex({属性:1})   # 1 正序, -1 倒叙\n",
    "```\n",
    "\n",
    "我们多加一些数据到mongodb. 分别看看加索引和不加索引的执行效率.\n",
    "\n",
    "```mongo\n",
    "for(i = 1; i < 100000; i++) db.tt.insert({\"test\": 'god'+i})\n",
    "```\n",
    "\n",
    "**查询:**\n",
    "\n",
    "```mongo\n",
    "db.tt.find({test:'god99999'}).explain(\"executionStats\")\n",
    "```\n",
    "\n",
    "**查询效率:**\n",
    "\n",
    "\"executionTimeMillis\" : 64,\n",
    "\n",
    "**加索引:**\n",
    "\n",
    "```\n",
    "db.tt.ensureIndex({test:1})\n",
    "```\n",
    "\n",
    "**再次查询:**\n",
    "\n",
    "\"executionTimeMillis\" : 0,\n",
    "\n",
    "\n",
    "**查看所有索引:**\n",
    "\n",
    "```\n",
    "db.collection_name.getIndexes()\n",
    "```\n",
    "\n",
    "**删除索引:**\n",
    "\n",
    "```\n",
    "db.collection_name.dropIndex({属性: 1})\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e4966b8",
   "metadata": {},
   "source": [
    "## MongoDB的权限管理\n",
    "\n",
    "mongodb的用户权限是跟着数据库走的，除了超级管理员外，其他管理员只能管理自己的库\n",
    "\n",
    "创建超级管理员\n",
    "\n",
    "首先, 将数据库调整到admin库.\n",
    "\n",
    "```mongo\n",
    "use admin\n",
    "```\n",
    "\n",
    "然后, 创建一个root超级管理员账号\n",
    "\n",
    "```\n",
    "db.createUser({user:\"用户名\", pwd: \"密码\", roles:['root']})\n",
    "db.createUser({user:\"sylar\", pwd: \"123456\", roles:['root']})\n",
    "```\n",
    "\n",
    "创建完成后. 需要退出mongodb. 然后修改配置文件:\n",
    "\n",
    "mac和linux:\n",
    "\n",
    "```config\n",
    "dbpath=/usr/local/mongodb\n",
    "port=27017\n",
    "logpath=/usr/local/var/log/mongodb/mongo.log\n",
    "fork=true\n",
    "logappend=true\n",
    "auth=true  # 加上账户认证\n",
    "```\n",
    "\n",
    "windows:\n",
    "\n",
    "```config\n",
    "storage:\n",
    "  dbPath: D:\\MongoDB\\Server\\4.4\\data\n",
    "  journal:\n",
    "    enabled: true\n",
    "\n",
    "systemLog:\n",
    "  destination: file\n",
    "  logAppend: true\n",
    "  path:  D:\\MongoDB\\Server\\4.4\\log\\mongod.log\n",
    "\n",
    "net:\n",
    "  port: 27017\n",
    "  bindIp: 127.0.0.1\n",
    "\n",
    "# 注意: security要顶格, authorization要空两格, enabled前面要有个空格\n",
    "security:\n",
    "  authorization: enabled\n",
    "```\n",
    "\n",
    "然后, 需要重新启动mongodb的服务(linux和mac直接杀掉进程, 重新启动即可, windows去系统服务里重启MongoDB的服务).\n",
    "\n",
    "然后重新打开mongo, 先进入admin, 登录超级管理员账号, 进入到你想要单独创建管理员的数据库. 然后创建出该数据库的管理员账号\n",
    "\n",
    "```\n",
    "> use admin\n",
    "switched to db admin\n",
    "> db.auth(\"sylar\",\"123456\")\n",
    "1\n",
    "> use ddd\n",
    "switched to db ddd\n",
    "> db.createUser({user:\"ttt_admin\", pwd:\"123456\", roles:[\"readWrite\"]})\n",
    "```\n",
    "\n",
    "退出管理员账号, 重新登录刚刚创建好的账号\n",
    "\n",
    "```\n",
    "> use ddd\n",
    "switched to db ddd\n",
    "> db.auth(\"ttt_admin\", \"123456\")\n",
    "1\n",
    "> db.stu.insert({name: 123, age:3})\n",
    "WriteResult({ \"nInserted\" : 1 })\n",
    ">\n",
    "```\n",
    "\n",
    "==注意, 每个账号只能管理自己的数据库(可以是多个).=="
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e36db83",
   "metadata": {},
   "source": [
    "## pymongo的使用"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fde2d24",
   "metadata": {},
   "source": [
    "### 建立连接"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "816dd7c3",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-10-31T02:30:05.399441Z",
     "start_time": "2023-10-31T02:30:00.436333Z"
    },
    "collapsed": true
   },
   "outputs": [
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "Input \u001b[0;32mIn [7]\u001b[0m, in \u001b[0;36m<cell line: 14>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      9\u001b[0m \u001b[38;5;66;03m# # 登录该数据库\u001b[39;00m\n\u001b[1;32m     10\u001b[0m \u001b[38;5;66;03m# py.authenticate(\"python_admin\", '123456')\u001b[39;00m\n\u001b[1;32m     11\u001b[0m \n\u001b[1;32m     12\u001b[0m \u001b[38;5;66;03m# 简单来个查询\u001b[39;00m\n\u001b[1;32m     13\u001b[0m result \u001b[38;5;241m=\u001b[39m py[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstu\u001b[39m\u001b[38;5;124m\"\u001b[39m]\u001b[38;5;241m.\u001b[39mfind()\n\u001b[0;32m---> 14\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m r \u001b[38;5;129;01min\u001b[39;00m result:\n\u001b[1;32m     15\u001b[0m     \u001b[38;5;28mprint\u001b[39m(r)\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/cursor.py:1280\u001b[0m, in \u001b[0;36mCursor.next\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1278\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__empty:\n\u001b[1;32m   1279\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m\n\u001b[0;32m-> 1280\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__data) \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_refresh\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m:\n\u001b[1;32m   1281\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__manipulate:\n\u001b[1;32m   1282\u001b[0m         _db \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__collection\u001b[38;5;241m.\u001b[39mdatabase\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/cursor.py:1165\u001b[0m, in \u001b[0;36mCursor._refresh\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   1162\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__data)\n\u001b[1;32m   1164\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__session:\n\u001b[0;32m-> 1165\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__session \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__collection\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdatabase\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mclient\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_ensure_session\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   1167\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__id \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:  \u001b[38;5;66;03m# Query\u001b[39;00m\n\u001b[1;32m   1168\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__min \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__max) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__hint:\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/mongo_client.py:2027\u001b[0m, in \u001b[0;36mMongoClient._ensure_session\u001b[0;34m(self, session)\u001b[0m\n\u001b[1;32m   2022\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m session\n\u001b[1;32m   2024\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m   2025\u001b[0m     \u001b[38;5;66;03m# Don't make implicit sessions causally consistent. Applications\u001b[39;00m\n\u001b[1;32m   2026\u001b[0m     \u001b[38;5;66;03m# should always opt-in.\u001b[39;00m\n\u001b[0;32m-> 2027\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__start_session\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcausal_consistency\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m   2028\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (ConfigurationError, InvalidOperation):\n\u001b[1;32m   2029\u001b[0m     \u001b[38;5;66;03m# Sessions not supported, or multiple users authenticated.\u001b[39;00m\n\u001b[1;32m   2030\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/mongo_client.py:1976\u001b[0m, in \u001b[0;36mMongoClient.__start_session\u001b[0;34m(self, implicit, **kwargs)\u001b[0m\n\u001b[1;32m   1971\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m InvalidOperation(\n\u001b[1;32m   1972\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCannot call start_session when\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m multiple users are authenticated\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m   1973\u001b[0m     )\n\u001b[1;32m   1975\u001b[0m \u001b[38;5;66;03m# Raises ConfigurationError if sessions are not supported.\u001b[39;00m\n\u001b[0;32m-> 1976\u001b[0m server_session \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_server_session\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   1977\u001b[0m opts \u001b[38;5;241m=\u001b[39m client_session\u001b[38;5;241m.\u001b[39mSessionOptions(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m   1978\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m client_session\u001b[38;5;241m.\u001b[39mClientSession(\u001b[38;5;28mself\u001b[39m, server_session, opts, authset, implicit)\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/mongo_client.py:2013\u001b[0m, in \u001b[0;36mMongoClient._get_server_session\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m   2011\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_get_server_session\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m   2012\u001b[0m \u001b[38;5;250m    \u001b[39m\u001b[38;5;124;03m\"\"\"Internal: start or resume a _ServerSession.\"\"\"\u001b[39;00m\n\u001b[0;32m-> 2013\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_topology\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_server_session\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/topology.py:525\u001b[0m, in \u001b[0;36mTopology.get_server_session\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    522\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock:\n\u001b[1;32m    523\u001b[0m     \u001b[38;5;66;03m# Sessions are always supported in load balanced mode.\u001b[39;00m\n\u001b[1;32m    524\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_settings\u001b[38;5;241m.\u001b[39mload_balanced:\n\u001b[0;32m--> 525\u001b[0m         session_timeout \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_check_session_support\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    526\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m    527\u001b[0m         \u001b[38;5;66;03m# Sessions never time out in load balanced mode.\u001b[39;00m\n\u001b[1;32m    528\u001b[0m         session_timeout \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mfloat\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minf\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/topology.py:507\u001b[0m, in \u001b[0;36mTopology._check_session_support\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    505\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_description\u001b[38;5;241m.\u001b[39mtopology_type \u001b[38;5;241m==\u001b[39m TOPOLOGY_TYPE\u001b[38;5;241m.\u001b[39mSingle:\n\u001b[1;32m    506\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_description\u001b[38;5;241m.\u001b[39mhas_known_servers:\n\u001b[0;32m--> 507\u001b[0m         \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_select_servers_loop\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    508\u001b[0m \u001b[43m            \u001b[49m\u001b[43many_server_selector\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_settings\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mserver_selection_timeout\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\n\u001b[1;32m    509\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    510\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_description\u001b[38;5;241m.\u001b[39mreadable_servers:\n\u001b[1;32m    511\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_select_servers_loop(\n\u001b[1;32m    512\u001b[0m         readable_server_selector, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_settings\u001b[38;5;241m.\u001b[39mserver_selection_timeout, \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m    513\u001b[0m     )\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/pymongo/topology.py:238\u001b[0m, in \u001b[0;36mTopology._select_servers_loop\u001b[0;34m(self, selector, timeout, address)\u001b[0m\n\u001b[1;32m    232\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_request_check_all()\n\u001b[1;32m    234\u001b[0m \u001b[38;5;66;03m# Release the lock and wait for the topology description to\u001b[39;00m\n\u001b[1;32m    235\u001b[0m \u001b[38;5;66;03m# change, or for a timeout. We won't miss any changes that\u001b[39;00m\n\u001b[1;32m    236\u001b[0m \u001b[38;5;66;03m# came after our most recent apply_selector call, since we've\u001b[39;00m\n\u001b[1;32m    237\u001b[0m \u001b[38;5;66;03m# held the lock until now.\u001b[39;00m\n\u001b[0;32m--> 238\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_condition\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwait\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcommon\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mMIN_HEARTBEAT_INTERVAL\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    239\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_description\u001b[38;5;241m.\u001b[39mcheck_compatible()\n\u001b[1;32m    240\u001b[0m now \u001b[38;5;241m=\u001b[39m _time()\n",
      "File \u001b[0;32m~/opt/anaconda3/lib/python3.9/threading.py:316\u001b[0m, in \u001b[0;36mCondition.wait\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m    314\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m    315\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m timeout \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[0;32m--> 316\u001b[0m         gotit \u001b[38;5;241m=\u001b[39m \u001b[43mwaiter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43macquire\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    317\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m    318\u001b[0m         gotit \u001b[38;5;241m=\u001b[39m waiter\u001b[38;5;241m.\u001b[39macquire(\u001b[38;5;28;01mFalse\u001b[39;00m)\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "import pymongo\n",
    "\n",
    "# 建立连接\n",
    "conn = pymongo.MongoClient(host='localhost', port=27017)\n",
    "\n",
    "# 切换数据库\n",
    "py = conn['MyMongoDB']\n",
    "\n",
    "# 登录该数据库\n",
    "py.authenticate(\"python_admin\", '123456')\n",
    "\n",
    "# 简单来个查询\n",
    "result = py[\"stu\"].find()\n",
    "for r in result:\n",
    "    print(r)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ce60d4f",
   "metadata": {},
   "source": [
    "### 完成增删改查"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad4d86da",
   "metadata": {},
   "outputs": [],
   "source": [
    "from concurrent.futures import ThreadPoolExecutor\n",
    "import mongodb\n",
    "from lxml import etree\n",
    "import requests\n",
    "import pymongo\n",
    "from pymongo import MongoClient\n",
    "\n",
    "\n",
    "def get_db(database, user, pwd):\n",
    "    client = MongoClient(host=\"localhost\", port=27017)\n",
    "    db = client[database]\n",
    "    # 有账号就加上验证, 没有账号就不用验证\n",
    "    db.authenticate(user, pwd)\n",
    "    return db\n",
    "\n",
    "\n",
    "# 增删改查\n",
    "# 增加数据\n",
    "def add_one(table, data):\n",
    "    db = get_db(\"python\", \"python_admin\", \"123456\")\n",
    "    result = db[table].insert_one(data)\n",
    "    return result\n",
    "\n",
    "\n",
    "def add_many(table, data_list):\n",
    "    db = get_db(\"python\", \"python_admin\", \"123456\")\n",
    "    result = db[table].insert_many(data_list)\n",
    "    return result.inserted_ids\n",
    "\n",
    "\n",
    "def upd(table, condition, data):\n",
    "    db = get_db(\"python\", \"python_admin\", \"123456\")\n",
    "    data = {'hehe': 'hehe', 'meme': 'meme'}\n",
    "    # result = db[table].update_many(condition, {\"$set\": data})\n",
    "    result = db[table].update_many(condition, {'$set': data})\n",
    "    return result\n",
    "\n",
    "\n",
    "def delete(table, condition):\n",
    "    db = get_db(\"python\", \"python_admin\", \"123456\")\n",
    "    result = db[table].remove(condition)\n",
    "    return result\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    # r = add_one(\"stu\", {\"name\": \"西瓜\", \"age\":18})\n",
    "    # print(r.inserted_id)\n",
    "    # r = add_many(\"stu\", [{\"name\": \"嘎嘎\"},{\"name\": \"咔咔\"}])\n",
    "    # print(r.inserted_ids)\n",
    "\n",
    "    # result = upd(\"stu\", {\"name\": 99999}, {\"age\": 100})\n",
    "    # print(result)\n",
    "\n",
    "    result = delete(\"stu\", {\"name\": \"哈哈\"})\n",
    "    print(result)\n",
    "\n",
    "\n",
    "\n",
    "def get_page_source(url):\n",
    "    resp = requests.get(url)\n",
    "    page_source = resp.text\n",
    "    return page_source\n",
    "\n",
    "\n",
    "def parse_html(html):\n",
    "    tree = etree.HTML(html)\n",
    "    # print(html)\n",
    "    li_list = tree.xpath(\"//ul[@class='sellListContent']/li\")\n",
    "    print(\"==>\", len(li_list))\n",
    "    try:\n",
    "        lst = []\n",
    "        for li in li_list:\n",
    "            title = li.xpath(\"./div[1]/div[1]/a/text()\")[0]\n",
    "            position_info = \"-\".join((s.strip()\n",
    "                                     for s in li.xpath(\"./div[1]/div[2]/div/a/text()\")))\n",
    "\n",
    "            temp = li.xpath(\"./div[1]/div[3]/div/text()\")[0].split(\" | \")\n",
    "            if len(temp) == 6:\n",
    "                temp.insert(5, \"\")\n",
    "            elif len(temp) == 8:\n",
    "                temp.pop()\n",
    "            huxing, mianji, chaoxiang, zhangxiu, louceng, nianfen, jiegou = temp\n",
    "            guanzhu, fabushijian = li.xpath(\n",
    "                \"./div[1]/div[4]/text()\")[0].split(\" / \")\n",
    "            tags = li.xpath(\"./div[1]/div[5]/span/text()\")\n",
    "\n",
    "            data = {\n",
    "                \"title\": title,\n",
    "                \"position\": position_info,\n",
    "                \"huxing\": huxing,\n",
    "                \"mianji\": mianji,\n",
    "                \"chaoxiang\": chaoxiang,\n",
    "                \"zhangxiu\": zhangxiu,\n",
    "                \"louceng\": louceng,\n",
    "                \"nianfen\": nianfen,\n",
    "                \"jiegou\": jiegou,\n",
    "                \"guanzhu\": guanzhu,\n",
    "                \"fabushijian\": fabushijian,\n",
    "                \"tags\": tags\n",
    "            }\n",
    "            lst.append(data)\n",
    "        # 一起存入mongodb\n",
    "        print(f\"数据量\", len(lst))\n",
    "        result = mongodb.add_many(\"ershoufang\", lst)\n",
    "        print(f\"插入{len(result)}\")\n",
    "    except Exception as e:\n",
    "        print(e)\n",
    "        print(temp)\n",
    "\n",
    "\n",
    "def main(url):\n",
    "    page_source = get_page_source(url)\n",
    "    parse_html(page_source)\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    with ThreadPoolExecutor(10) as t:\n",
    "        for i in range(1, 31):\n",
    "            url = f\"https://bj.lianjia.com/ershoufang/pg{i}/\"\n",
    "            t.submit(main, url)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d621aa64",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19ebd2eb",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "278.797px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
